home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume16 / xfmt < prev    next >
Encoding:
Internet Message Format  |  1988-11-10  |  40.9 KB

  1. Subject:  v16i071:  A simple formatter
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: lee@uhccux.uhcc.hawaii.edu (Greg Lee)
  7. Posting-number: Volume 16, Issue 71
  8. Archive-name: xfmt
  9.  
  10. [  This will be the last one of these, unless anyone has an nroff
  11.    emulator, as we're moving past the "simple" stage now.
  12.    Note that it uses FLEX, which appeared here several months
  13.    ago.  --r$  ]
  14.  
  15. Xfmt fills out lines by paragraphs, like the BSD fmt program.
  16. The first version of xfmt, 'extended fmt', was written by Bill Gray
  17. (bgray@marque.mu.edu) and appeared in comp.sources.misc as "fmt".
  18.  
  19. This version interprets a few nroff -man commands or a (very) few
  20. TeX commands, or both, if you ask it to (by using the -m or -x flags).
  21. It does a more complete job of interpreting fonts in terms of screen
  22. attributes than can be done nroff(1) and ul(1).  There is also a -c flag
  23. for displaying C code with comments highlighted and keywords shown with
  24. various screen attributes.
  25.  
  26. Many man pages are not correctly processed, since many have nroff
  27. commands not interpreted by xfmt.  The addition of -man interpretation
  28. and other features to xfmt will not be to everyone's taste, especially
  29. since they are incompletely implemented.
  30.  
  31. The BSD termcap facility is used in this version of xfmt.  Also, you
  32. need flex, by Vern Paxson et al. to make xfmt.  Unless a second version
  33. of flex has been distributed by now, you will need to modify flex's
  34. skeleton files by making the changes described in the REAMDE file.
  35.  
  36.             --    Greg Lee
  37. U.S.mail: 562 Moore Hall, Dept. of Linguistics, Univ. of Hawaii, HONO, HI 96822
  38. INTERNET: lee@uhccux.uhcc.hawaii.edu
  39. UUCP:     {ihnp4,dcdwest,ucbvax}!sdcsvax!nosc!uhccux!lee
  40. BITNET:   lee@uhccux
  41.  
  42. #! /bin/sh
  43. # This is a shell archive.  Remove anything before this line, then unpack
  44. # it by saving it into a file and typing "sh file".  To overwrite existing
  45. # files, type "sh file -c".  You can also feed this as standard input via
  46. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  47. # will see the following message at the end:
  48. #        "End of archive 1 (of 1)."
  49. # Contents:  MANIFEST Makefile README cmds.tex flex.skel.diff xfmt.1 xfmt.l
  50. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  51. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  52.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  53. else
  54. echo shar: Extracting \"'MANIFEST'\" \(402 characters\)
  55. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  56. X   File Name        Archive #    Description
  57. X-----------------------------------------------------------
  58. X MANIFEST                   1    
  59. X Makefile                   1    
  60. X README                     1    
  61. X cmds.tex                   1    list of formatting commands
  62. X flex.skel.diff             1    patch for flex distribution file
  63. X xfmt.1                     1    man page
  64. X xfmt.l                     1    (f)lex source for xfmt
  65. END_OF_FILE
  66. if test 402 -ne `wc -c <'MANIFEST'`; then
  67.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  68. fi
  69. # end of 'MANIFEST'
  70. fi
  71. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  72.   echo shar: Will not clobber existing file \"'Makefile'\"
  73. else
  74. echo shar: Extracting \"'Makefile'\" \(791 characters\)
  75. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  76. X# file: xfmt/Makefile
  77. X# 04/88  bgray, rev. 05/88 by Greg Lee
  78. X
  79. X
  80. BINDIR = /usr/lbin
  81. MANDIR = /usr/man/u_man/man1
  82. CATMAN = /usr/catman/u_man/man1
  83. X
  84. LIBS = -ltermcap
  85. CFLAGS = -O
  86. LDFLAGS = -s
  87. CC = /bin/cc
  88. RM = /bin/rm -f
  89. CP = /bin/cp
  90. X
  91. OBJS =
  92. X
  93. X
  94. all: xfmt
  95. X
  96. xfmt:    xfmt.c
  97. X    $(CC) $(CFLAGS) $(LDFLAGS) -o xfmt xfmt.c $(LIBS)
  98. X
  99. xfmt.c:    xfmt.l
  100. X    @rm -f xfmt.c
  101. X    flex -t xfmt.l >xfmt.c
  102. X
  103. xfmt.doc: xfmt.1 xfmt
  104. X    xfmt -jmo xfmt.1 >xfmt.doc
  105. X
  106. shar:    xfmt.l xfmt.1 README Makefile MANIFEST cmds.tex flex.skel.diff
  107. X    @rm -f xfmt.shar
  108. X    makekit -m -nxfmt.shar.
  109. X
  110. install: all xfmt.doc
  111. X    $(CP) xfmt $(BINDIR)
  112. X    chown bin $(BINDIR)/xfmt
  113. X    chgrp bin $(BINDIR)/xfmt
  114. X    chmod 755 $(BINDIR)/xfmt
  115. X    $(CP) xfmt.doc $(CATMAN)/xfmt.1
  116. X    chown bin $(CATMAN)/xfmt.1
  117. X    chgrp bin $(CATMAN)/xfmt.1
  118. X    chmod 644 $(CATMAN)/xfmt.1
  119. X
  120. clean:
  121. X    rm xfmt.c
  122. END_OF_FILE
  123. if test 791 -ne `wc -c <'Makefile'`; then
  124.     echo shar: \"'Makefile'\" unpacked with wrong size!
  125. fi
  126. # end of 'Makefile'
  127. fi
  128. if test -f 'README' -a "${1}" != "-c" ; then 
  129.   echo shar: Will not clobber existing file \"'README'\"
  130. else
  131. echo shar: Extracting \"'README'\" \(2168 characters\)
  132. sed "s/^X//" >'README' <<'END_OF_FILE'
  133. X
  134. The first version of xfmt, 'extended fmt', was written by Bill Gray
  135. X(bgray@marque.mu.edu) and appeared in comp.sources.misc as "fmt".
  136. Since it is nearly downward compatible with the BSD fmt program
  137. X(treatment of ending sentence punctuation is a little different), you
  138. might choose to name your version "xfmt" -- or not.
  139. X
  140. This version interprets a few nroff -man commands or a (very) few
  141. TeX commands, or both, if you ask it to (by using the -m or -x flags).
  142. It does a more complete job of interpreting fonts in terms of screen
  143. attributes than can be done nroff(1) and ul(1).  There is also a -c flag
  144. for displaying C code with comments highlighted and keywords shown with
  145. various screen attributes.
  146. X
  147. Many man pages are not correctly processed, since many have nroff
  148. commands not interpreted by xfmt.  The addition of -man interpretation
  149. and other features to xfmt will not be to everyone's taste, especially
  150. since they are incompletely implemented.
  151. X
  152. The BSD termcap facility is used in this version of xfmt.  Also, you
  153. need flex, by Vern Paxson et al. to make xfmt.  Unless a second version
  154. of flex has been distributed by now, you will need to modify flex's
  155. skeleton files by making the following changes:
  156. X
  157. CHANGE
  158. static int yy_start;        /* start state number */
  159. TO
  160. static int yy_start = 0;    /* start state number */
  161. X
  162. CHANGE
  163. X    yy_start = 1;        /* first start state */
  164. TO
  165. X    if (!yy_start) yy_start = 1;    /* first start state */
  166. X
  167. Or you can try "patch < flex.skel.diff" to make the changes
  168. automatically in the distributed version of the file flex.skel.  (This
  169. patch file includes another patch concerning the reject action.) The
  170. change to flex is required so xfmt can choose a start condition in its
  171. main() procedure depending on what flags it sees on the command line.
  172. X
  173. Once you have made xfmt, the accompanying documents can be displayed
  174. with:
  175. X    xfmt -mu xfmt.1
  176. X    xfmt -xu cmds.tex
  177. X    xfmt -c xfmt.l
  178. X
  179. X
  180. The amount of pattern matching done in this version of xfmt exceeds the
  181. capacity of lex by quite a bit.  This kind of program is now easy to do
  182. thanks to the implementors of flex:  Vern Paxson, Kevin Gong, Jef
  183. Poskanzer, Van Jacobson.
  184. X
  185. X        Greg Lee, lee@uhccux.uhcc.hawaii.edu
  186. END_OF_FILE
  187. if test 2168 -ne `wc -c <'README'`; then
  188.     echo shar: \"'README'\" unpacked with wrong size!
  189. fi
  190. # end of 'README'
  191. fi
  192. if test -f 'cmds.tex' -a "${1}" != "-c" ; then 
  193.   echo shar: Will not clobber existing file \"'cmds.tex'\"
  194. else
  195. echo shar: Extracting \"'cmds.tex'\" \(5328 characters\)
  196. sed "s/^X//" >'cmds.tex' <<'END_OF_FILE'
  197. X
  198. X{\it xfmt} formatting commands.}
  199. X\bigskip
  200. X
  201. X\centerline{\it Nroff/man~commands with \tt xfmt~-mu}
  202. X\medskip
  203. X
  204. X\item{\tt .sp~(n)}    Skip 1 (or n) lines.
  205. X\item{\tt \\fI}        Start {\it underlining} of text (termcap "ul").
  206. X\item{\tt \\fB}        Start {\bf bold} text (termcap "md").
  207. X\item{\tt \\fS}        Start {\tt reversed} text (termcap "mr").
  208. X\item{\tt \\fG}        Start {\sl blinking} text (termcap "mb").
  209. X\item{\tt \\fR}        End {\it underlining} or other special text
  210. X            (termcap "me"/"ue").
  211. X\item{\tt \\fP}        Same as {\tt \\fR} (bug).
  212. X\item{\tt .nf}        Stop filling lines to maximum width.
  213. X\item{\tt .fi}        Resume filling lines to maximum width.
  214. X\item{\tt .I~<line>}    Display <line> {\it underlined}.
  215. X\item{\tt .B~<line>}    Display <line> in {\bf bold}.
  216. X\item{\tt .S~<line>}    Display <line> {\tt reversed}.
  217. X\item{\tt .G~<line>}    Display <line> {\sl blinking}.
  218. X\item{\tt .SM~<line>}    Display <line> {\tt reversed}.
  219. X\item{\tt .R~<line>}    Display <line> plain.
  220. X\item{\tt .CT~<char>}    Display <char> reversed or "<CTRL/<char>>"
  221. X            in case neither -u or -o was given.
  222. X\item{\tt \\*(lq}    Display "`".
  223. X\item{\tt \\*(rq}    Display "'".
  224. X\item{\tt \\(*<char>}    Display <char> reversed.
  225. X\item{\tt \\(<char><char>}
  226. X            Display <char><char> reversed.
  227. X\item{\tt \\s(-)<digit>}
  228. X            Ignored.
  229. X\item{\tt \\| \\\^ \\\& \\! \\\{ \\\} \\a \\c \\d \\e \\p \\r \\t \\u \\z}
  230. X            Ignored.
  231. X\item{\tt \\}        Display following character (except as above).
  232. X\item{\tt .br}        Terminate preceding paragraph.
  233. X\item{\tt .PP}        Terminate preceding paragraph.
  234. X\item{\tt .P}        Terminate preceding paragraph.
  235. X\item{\tt .LP}        Terminate preceding paragraph.
  236. X\item{\tt .TP~(n)}    Begin hanging paragraph with 5 (or n) extra
  237. X            spaces of indentation at left, with first
  238. X            following line in left margin.
  239. X\item{\tt .IP~<word>~(0.3i)~...}
  240. X            Begin hanging paragraph with 5 extra
  241. X            spaces of indentation at left, with <word> ...
  242. X            in left margin.
  243. X\item{\tt .HP~(n)}    Begin hanging paragraph with 5 extra
  244. X            spaces of indentation at left.
  245. X\item{\tt .RS}        Indent 5 extra spaces until {\tt .RE}.
  246. X\item{\tt .RE}        Resume normal indent after {\tt .RS}.
  247. X\item{\tt .DS}        Skip a line; preserve lines and spacing;
  248. X            indent 5 extra spaces until {\tt .DE}.
  249. X\item{\tt .DE}        Resume filling and normal indent after {\tt .DS}.
  250. X\item{\tt .EX}        Skip a line; preserve lines and spacing;
  251. X            indent 5 extra spaces until {\tt .EE}.
  252. X\item{\tt .EE}        Skip a line; resume filling and normal indent
  253. X            after {\tt .EX}.
  254. X\item{\tt .VS~<line>}    Ignored.
  255. X\item{\tt .VE~<line>}    Ignored.
  256. X\item{\tt .NT~(<line>)}    Skip a line, indent 5 extra spaces, shorten
  257. X            line length by 5, display {\bf NOTE} bold and
  258. X            centered (or <line>), continue until {\tt .NE}.
  259. X\item{\tt .NE}        Resume normal indent and line length after
  260. X            {\tt .NT}.
  261. X\item{\tt .IR~<words>}    Join words alternating {\it underlined} and plain.
  262. X\item{\tt .BR~<words>}    Join words alternating {\bf bold} and plain.
  263. X\item{\tt .RI~<words>}    Join words alternating plain and {\it underlined}.
  264. X\item{\tt .BI~<words>}    Join words alternating {\bf bold} and {\it underlined}.
  265. X\item{\tt .RB~<words>}    Join words alternating plain and {\bf bold}.
  266. X\item{\tt .IB~<words>}    Join words alternating {\it underlined} and {\bf bold}.
  267. X\item{\tt .SH~<line>}    Skip a line, and display <line> left adjusted
  268. X            and {\bf bold}.
  269. X\item{\tt .SS~<line>}    Skip a line, and display <line> {\bf bold}.
  270. X\item{\tt .TH~<name>~<n>~(<text>)}
  271. X            Right adjust {\bf <name>(<n>)} (followed by <text>).
  272. X\item{\tt .UC~(<digit>)}
  273. X            Ignored.
  274. X\item{\tt .\\"~<line>}    Ignore <line>.
  275. X\item{\tt .PN~<line>}    Underline <line>.
  276. X\item{\tt .ta~<line>}    Ignore <line>.
  277. X\item{\tt .PD~<line>}    Ignore <line>.
  278. X\item{\tt .NX<cap>~<line>}
  279. X            Ignore <line>.
  280. X\item{\tt .DT}        Ignored.
  281. X\item{\tt .ti~+n~<line>}
  282. X            n extra spaces of indentation at left of <line>.
  283. X\item{\tt .MS~<word>~<n>}
  284. X            Display {\it <word>(<n>)}.
  285. X
  286. X
  287. X\bigskip
  288. X\centerline{\it \TeX ~commands with \tt xfmt~-xu}
  289. X\medskip
  290. X
  291. X\item{\tt \\vskip}    Skip a line.
  292. X\item{\tt \\bigskip}    Skip a line.
  293. X\item{\tt \\medskip}    Skip a line.
  294. X\item{\tt \\smallskip}    Skip a line.
  295. X\item{\tt \\\$ \\\# \\\{ \\\} \\\& \\\% \\^ \\_ \\\~ \\' \\" \\\\}
  296. X            Display character following \\.
  297. X\item{\tt\\backslash}    Display \backslash.
  298. X\item{\tt \\it}        Begin {\it underlining} (termcap "ul").
  299. X\item{\tt \\sl}        Begin {\sl blinking} (termcap "mb").
  300. X\item{\tt \\bf}        Begin {\bf bold} (termcap "md").
  301. X\item{\tt \\rm}        Begin plain.
  302. X\item{\tt \\tt}        Begin {\tt reverse} (termcap "mr").
  303. X\item{\tt \\TeX}    Display \TeX.
  304. X\item{\tt \\centerline~<line>}
  305. X            Display <line> centered.
  306. X\item{\tt\\beginsection~<line>}
  307. X            Skip a line, display <line> in bold.
  308. X\item{\tt \\rightline~<line>}
  309. X            Display <line> right adjusted.
  310. X\item{\tt \\raggedright}
  311. X            Stop justifying (for current \{...\} group).
  312. X\item{\tt \\obeylines}    Stop filling lines and preserve spacing
  313. X            (for current \{...\} group).
  314. X\item{\tt \\obeyspaces} Stop filling lines and preserve spacing
  315. X            (for current \{...\} group).
  316. X\item{\tt \\item\{...\}}
  317. X            Start hanging paragraph with 10 extra
  318. X            spaces of left indentation and ... displayed in
  319. X            left margin and indented 5.
  320. X\item{\tt \\itemitem\{...\}}
  321. X            Same as {\tt \\item}.
  322. X\item{\tt \\<space-character>}
  323. X            Break between words.
  324. X\item{\tt \~}        Space that does not break between words and
  325. X            is displayed with current display attribute.
  326. X\item{\tt \$}        Ignored.
  327. X\item{\tt \#}        Ignored.
  328. X
  329. X\bigskip
  330. X\rightline{Greg Lee, May, 1988}
  331. X\bye
  332. END_OF_FILE
  333. if test 5328 -ne `wc -c <'cmds.tex'`; then
  334.     echo shar: \"'cmds.tex'\" unpacked with wrong size!
  335. fi
  336. # end of 'cmds.tex'
  337. fi
  338. if test -f 'flex.skel.diff' -a "${1}" != "-c" ; then 
  339.   echo shar: Will not clobber existing file \"'flex.skel.diff'\"
  340. else
  341. echo shar: Extracting \"'flex.skel.diff'\" \(1605 characters\)
  342. sed "s/^X//" >'flex.skel.diff' <<'END_OF_FILE'
  343. X*** flex.skel.orig    Tue May 31 16:32:11 1988
  344. X--- flex.skel        Tue May 31 16:35:25 1988
  345. X***************
  346. X*** 12,18
  347. X  /* these variables are all declared out here so that section 3 code can
  348. X   * manipulate them
  349. X   */
  350. X! static int yy_start, yy_b_buf_p, yy_c_buf_p, yy_e_buf_p;
  351. X  static int yy_saw_eof, yy_init = 1;
  352. X  
  353. X  /* yy_ch_buf has to be 1 character longer than YY_BUF_SIZE, since when
  354. X
  355. X--- 12,18 -----
  356. X  /* these variables are all declared out here so that section 3 code can
  357. X   * manipulate them
  358. X   */
  359. X! static int yy_start = 0, yy_b_buf_p, yy_c_buf_p, yy_e_buf_p;
  360. X  static int yy_saw_eof, yy_init = 1;
  361. X  
  362. X  /* yy_ch_buf has to be 1 character longer than YY_BUF_SIZE, since when
  363. X***************
  364. X*** 28,33
  365. X  YY_DECL
  366. X      {
  367. X      int yy_n_chars, yy_lp, yy_iii, yy_buf_pos, yy_act;
  368. X  
  369. X  %% user's declarations go here
  370. X  
  371. X
  372. X--- 28,36 -----
  373. X  YY_DECL
  374. X      {
  375. X      int yy_n_chars, yy_lp, yy_iii, yy_buf_pos, yy_act;
  376. X+ #ifdef FLEX_REJECT_ENABLED
  377. X+     int yy_full_match;
  378. X+ #endif
  379. X  
  380. X  %% user's declarations go here
  381. X  
  382. X***************
  383. X*** 34,40
  384. X      if ( yy_init )
  385. X      {
  386. X      YY_INIT;
  387. X!     yy_start = 1;
  388. X      yy_init = 0;
  389. X      }
  390. X  
  391. X
  392. X--- 37,43 -----
  393. X      if ( yy_init )
  394. X      {
  395. X      YY_INIT;
  396. X!     if (!yy_start) yy_start = 1;
  397. X      yy_init = 0;
  398. X      }
  399. X  
  400. X***************
  401. X*** 41,46
  402. X      goto get_next_token;
  403. X  
  404. X  do_action:
  405. X      for ( ; ; )
  406. X      {
  407. X      YY_DO_BEFORE_ACTION
  408. X
  409. X--- 44,55 -----
  410. X      goto get_next_token;
  411. X  
  412. X  do_action:
  413. X+ 
  414. X+ #ifdef FLEX_REJECT_ENABLED
  415. X+     /* remember matched text in case we back up due to trailing context */
  416. X+     yy_full_match = yy_c_buf_p;
  417. X+ #endif
  418. X+ 
  419. X      for ( ; ; )
  420. X      {
  421. X      YY_DO_BEFORE_ACTION
  422. END_OF_FILE
  423. if test 1605 -ne `wc -c <'flex.skel.diff'`; then
  424.     echo shar: \"'flex.skel.diff'\" unpacked with wrong size!
  425. fi
  426. # end of 'flex.skel.diff'
  427. fi
  428. if test -f 'xfmt.1' -a "${1}" != "-c" ; then 
  429.   echo shar: Will not clobber existing file \"'xfmt.1'\"
  430. else
  431. echo shar: Extracting \"'xfmt.1'\" \(4161 characters\)
  432. sed "s/^X//" >'xfmt.1' <<'END_OF_FILE'
  433. X.TH XFMT 1 LOCAL
  434. X.SH NAME
  435. xfmt \- a simple text formatter
  436. X.SH SYNOPSIS
  437. X.B xfmt
  438. X[
  439. X.B \-i
  440. X] [
  441. X.B \-j
  442. X] [
  443. X.B \-m
  444. X] [
  445. X.B \-x
  446. X] [
  447. X.B \-o
  448. X] [
  449. X.B \-u
  450. X] [
  451. X.B \-c
  452. X] [
  453. X.B \-l n
  454. X] [
  455. X.B \-p n
  456. X] [
  457. X.B \-t n
  458. X] [ filenames ]
  459. X.SH DESCRIPTION
  460. X.I Xfmt
  461. is a simple text formatter.  With no options present, the default
  462. behavior of
  463. X.I xfmt
  464. is to copy its input (from specified files or from stdin, if no files
  465. are specified) to its output but with input reformatted into lines no
  466. longer than 72 characters long.  A blank line is taken to indicate the
  467. beginning of a new paragraph.  Lines that begin with a period are
  468. preserved.
  469. X.PP
  470. The following options modify this behavior:
  471. X.TP
  472. X.B \-i
  473. This option will cause
  474. X.I xfmt 
  475. to preserve indentations.  Blanks or tabs at the beginning of a line
  476. will be considered the beginning of a new paragraph.
  477. X.TP
  478. X.B \-j
  479. Justify output lines.  (The default behavior of
  480. X.I xfmt
  481. is to output lines with a ragged right margin).
  482. X.TP
  483. X.B \-m
  484. Interpret a few commonly used
  485. X.I nroff
  486. X-man commands.
  487. Those understood (in some fashion) are:
  488. X.DS
  489. X .B .I .R .S .G .SM .C
  490. X .IR .BR .RI .BI .RB .IB
  491. X .SH .SS .TH .PP .P .LP .TP .IP .HP
  492. X .RS .RE .DS .DE .NT .NE .VS .VE
  493. X .CT .PN .MS
  494. X .UC (ignored) .DT (ignored) .PD (ignored)
  495. X.DE
  496. X.sp
  497. And a few other nroff commands that occur commonly in man
  498. pages are recognized:
  499. X.DS
  500. X \\fI \\fB \\fR \\fP \\fC
  501. X .sp .br .nf .fi .ti
  502. X .\\" \\*(lq \\*(rq .ta (ignored)
  503. X.DE
  504. X.sp
  505. More details can be found in the document
  506. X.IR cmds.tex .
  507. X.TP
  508. X.B \-x
  509. Interpret a few commonly used
  510. X.I TeX
  511. commands.
  512. Those understood (in some fashion) are:
  513. X.DS
  514. X \\vskip \\bigskip \\medskip \\smallskip \\$ \\# \\{ \\}
  515. X \\& \\% \\^ \\_ \\~ \\' \\" \\\\ \\it \\sl \\bf \\rm \\tt
  516. X \\TeX \\centerline \\rightline \\raggedright \\obeylines \\item
  517. X { } \\(space) ~ $ (ignored) \\backslash \\beginsection
  518. X.DE
  519. X.TP
  520. X.B \-o
  521. Produce bold and underlined text with overstriking.
  522. If the terminal and termcap entries permit, the bold and underlined
  523. portions can be seen on the screen by feeding
  524. X.I xfmt
  525. output to
  526. X.MS ul 1 .
  527. Bold is produced by fonts B/bf, S/tt, and underlined
  528. by I/it, G/sl.
  529. X.TP
  530. X.B \-u
  531. Produce bold, underlined, reversed, and blinking text for terminal
  532. display (using termcap md, us, mr, and mb entries, respectively).
  533. This is useful only if one of the options -m or -x is also chosen.
  534. Bold is produced by font B/bf, underlined by I/it, reversed by S/tt,
  535. and blinking by G/sl.
  536. X.TP
  537. X.B \-c
  538. XFor C code, display comments reversed, flow-of-control keywords
  539. in bold, storage-class keywords underlined, and pre-processor
  540. keywords blinking.
  541. No formatting is done.  The -u option is assumed unless the -o
  542. option is given.
  543. X.TP
  544. X.B \-l n
  545. This option can be used to change the line length from the default of 72
  546. characters.
  547. X.TP
  548. X.B \-p n
  549. Change the page offset.  This option will cause the output lines to be
  550. offset the indicated number of columns from the left.
  551. X.TP
  552. X.B \-t n
  553. Set tab size.  This option is useful only with the
  554. X.B \-i 
  555. or
  556. X.B \-c
  557. options, or for text in the scope of .nf, .EX, .DS, \obeylines or \obeyspaces,
  558. since otherwise tabs are treated the same as space characters.
  559. X.SH EXAMPLES
  560. Display a man page
  561. X.I binmail.1
  562. on the screen with right justification, a page at a time:
  563. X.EX
  564. xfmt -jmu binmail.1 | more -f
  565. X.EE
  566. Display a man page with underlining, but no bold face:
  567. X.EX
  568. xfmt -mo binmail.1 | more -f
  569. X.EE
  570. Prepare a preformatted man page to be displayed with
  571. X.MS ul 1 :
  572. X.EX
  573. xfmt -mo binmail.1 >binmail.doc
  574. X.EE
  575. Display high-lighted C source code on the screen:
  576. X.EX
  577. xfmt -c \fIfile\fR.c
  578. X.EE
  579. X.SH TIPS
  580. In
  581. X.IR vi ,
  582. you can define a macro that will reformat paragraphs by typing
  583. X.I ":map V {!}xfmt^M" 
  584. or by putting the line
  585. X.RS
  586. X.I "map V {!}xfmt^M"
  587. X.RE
  588. in your
  589. X.I .exrc
  590. file.  After defining this macro, pressing
  591. X.I V 
  592. will cause the paragraph under the cursor to be reformatted.  (Use the
  593. X.I u
  594. key to
  595. X.I undo
  596. if necessary.
  597. X.SH "SEE ALSO"
  598. nroff(1), vi(1), ul(1)
  599. X.SH BUGS
  600. TeX command interpretation doesn't have a chance of working except
  601. for files prepared with the limitations of xfmt in mind.
  602. Nroff -man interpretation has maybe a 50-50 chance.
  603. X.SH AUTHORS
  604. original version: bgray@marque.mu.edu (Bill Gray)
  605. X.br
  606. TeX, man, C mods: lee@uhccux.uhcc.hawaii.edu (Greg Lee)
  607. END_OF_FILE
  608. if test 4161 -ne `wc -c <'xfmt.1'`; then
  609.     echo shar: \"'xfmt.1'\" unpacked with wrong size!
  610. fi
  611. # end of 'xfmt.1'
  612. fi
  613. if test -f 'xfmt.l' -a "${1}" != "-c" ; then 
  614.   echo shar: Will not clobber existing file \"'xfmt.l'\"
  615. else
  616. echo shar: Extracting \"'xfmt.l'\" \(21023 characters\)
  617. sed "s/^X//" >'xfmt.l' <<'END_OF_FILE'
  618. X%{
  619. X
  620. X/* 
  621. X * (was file: fmt.c)
  622. X * 04/88  bgray
  623. X * file: xfmt.l
  624. X * revised with (f)lex front end
  625. X * 05/88  Greg Lee
  626. X */
  627. X
  628. X/* a simple text formatter */
  629. X
  630. X#ifndef lint
  631. static    char xfmt_sccsid[] = "@(#)xfmt.l <05/30/88>";
  632. X#endif lint
  633. X
  634. X
  635. X#include <stdio.h>
  636. X#include <ctype.h>
  637. X#include <string.h>
  638. X
  639. X#ifndef TRUE
  640. X#define TRUE 1
  641. X#endif
  642. X#ifndef FALSE
  643. X#define FALSE 0
  644. X#endif
  645. X
  646. X/* character attributes controlled by font-changing commands */
  647. X#define ROMAN  1    /* plain, from \rm or .R */
  648. X#define ITALIC 2    /* underlined, from \it or .I */
  649. X#define BOLD   3    /* bold, from \bf or .B */
  650. X#define TTYPE  4    /* reversed, from \tt or .S */
  651. X#define SLANTY 5    /* blinking, from \sl or .G */
  652. X
  653. int     attribute = ROMAN,    /* current character attribute */
  654. X        nextattribute = 0;    /* attribute to restore after next
  655. X                 * word for .RB, etc. or after line
  656. X                 * for \beginsection
  657. X                 */
  658. char    nest[80];        /* stack of attributes for each current */
  659. int    level = 1;        /* TeX {}-group */
  660. X
  661. X/* global state of formatter */
  662. char    iflag  = FALSE,        /* preserving left indentation (-i)? */
  663. X        jflag  = FALSE,        /* requested justification with -j? */
  664. X        oflag  = FALSE,        /* requested overprint with -o? */
  665. X        uflag  = FALSE,        /* requested terminal output with -u? */
  666. X        xflag  = FALSE,        /* requested use TeX commands w. -x? */
  667. X        mflag  = FALSE,        /* requested use man commands w. -m? */
  668. X        cflag  = FALSE,        /* requested format C code w. -c? */
  669. X        qtflag = FALSE,        /* saw odd " in processing .RB etc.? */
  670. X        ceflag = FALSE,        /* center next output line? */
  671. X        raflag = FALSE,        /* right adjust next output line? */
  672. X        obflag = FALSE,        /* not concatenating? */
  673. X        njflag = FALSE;        /* not currently justifying? */
  674. X
  675. int     maxlen  = 72,
  676. X        tabsize = 8,
  677. X        indent  = 0,
  678. X        offset  = 0,
  679. X        tpstate = 0,        /* keep track for hanging indentation */
  680. X        tpvalue = 5,        /* amount of hang, from arg of .TP,.HP */
  681. X        spaces  = 0,        /* space to leave after current word */
  682. X        tempi;            /* misc. use in lex pattern section */
  683. X
  684. char   *progname = NULL;
  685. char   *usage = "usage: %s [-ijcmxou] [-l n] [-p n] [-t n] [file ...]\n";
  686. X
  687. int     dir = FALSE;
  688. int     holecnt = 0;
  689. char   *holeptr[256];        /* holeptr[0] is unused */
  690. X
  691. char    oline[2048] = "\0",    /* output line buffer */
  692. X       *olp = oline,
  693. X        aline[2048] = "\0",    /* output line attribute buffer */
  694. X       *alp = aline,
  695. X        oword[512] = "\0",    /* output word buffer */
  696. X       *owp = oword,
  697. X        aword[512] = "\0",    /* output word attribute buffer */
  698. X       *awp = aword;
  699. X
  700. extern char *optarg;        /* from getopt */
  701. extern int  optind;
  702. X
  703. int     max ();
  704. void    exit ();
  705. char   *basename ();
  706. void    copyindent ();
  707. void    puttc ();
  708. void    putts ();
  709. void    lbreak ();
  710. void    putword ();
  711. void    justifyline ();
  712. void    putline ();
  713. void    sputline ();
  714. void    skipline ();
  715. void    addparens ();
  716. void    terminit ();
  717. void    termattr ();
  718. X
  719. X%}
  720. X
  721. X/* lex start state for flags: -x, -m, (none), -mx, respectively */
  722. X%s    TEX MAN PLAIN ALL CCODE
  723. X
  724. X/* match end of TeX command */
  725. wh    [ \t]*/[^a-z]
  726. X
  727. X%%
  728. X
  729. X<MAN,ALL>^".sp"        skipline(1);
  730. X
  731. X/* match various TeX skip commands */
  732. X<TEX,ALL>\\[a-gi-z]+"skip"{wh}    skipline(1);
  733. X
  734. X/* blank line in input gives blank line in output -- not like real TeX */
  735. X\n$            skipline(1);
  736. X
  737. X<MAN,ALL>^".sp "[0-9]+    skipline(atoi(yytext+4));
  738. X
  739. X/* traditional */
  740. X<PLAIN>^\..* {
  741. X            lbreak();
  742. X            (void)printf("%s\n",yytext);
  743. X}
  744. X
  745. X/* escaped special characters -- \\ for \ not like real TeX */
  746. X<TEX,ALL>\\[$#{}&%^_~'"\\] puttc(yytext[1]);
  747. X
  748. X/* some font-changing commands */
  749. X
  750. X<TEX,ALL>"\\it"{wh} |
  751. X<MAN,ALL>"\\f"("I"|"C")    attribute = ITALIC;
  752. X
  753. X<TEX,ALL>"\\sl"{wh} |
  754. X<MAN,ALL>"\\fG"         attribute = SLANTY;
  755. X
  756. X<TEX,ALL>"\\bf"{wh} |
  757. X<MAN,ALL>"\\fB"         attribute = BOLD;
  758. X
  759. X<TEX,ALL>"\\rm"{wh} |
  760. X<MAN,ALL>"\\f"("R"|"P")    attribute = ROMAN; /* \fP should not be like \fR */
  761. X
  762. X<TEX,ALL>"\\tt"{wh} |
  763. X<MAN,ALL>"\\fS"         attribute = TTYPE;
  764. X
  765. X
  766. X<TEX,ALL>"\\TeX"{wh}    putts("TeX");
  767. X
  768. X/* should these 4 TeX commands cause breaks? */
  769. X<TEX,ALL>\\"centerline"{wh}    ceflag = TRUE;
  770. X
  771. X<TEX,ALL>\\"rightline"{wh}    raflag = TRUE;
  772. X
  773. X<TEX,ALL>\\"raggedright"{wh}    njflag = level;
  774. X
  775. X<TEX,ALL>\\"obeylines"{wh}    obflag = level;
  776. X
  777. X<MAN,ALL>^".nf"        lbreak(); obflag = TRUE;
  778. X
  779. X<MAN,ALL>^".fi"        lbreak(); obflag = FALSE;
  780. X
  781. X<TEX,ALL>"{"        nest[level++] = attribute; /* push attr. onto stack */
  782. X
  783. X<TEX,ALL>"}"  {        /* if emerging from {} in which \obeylines or
  784. X             * \raggedright occurred, cancel  (not a very general
  785. X             * strategy)
  786. X             */
  787. X            if (obflag == level) obflag = FALSE;
  788. X            if (njflag == level) njflag = FALSE;
  789. X            /* pop attribute off stack */
  790. X            if (level > 1) attribute = nest[--level];
  791. X            /* } after \item signals end of tag; will not
  792. X             * work right with {} inside tag */
  793. X            if (tpstate == 1)  {
  794. X                tpstate = 2;
  795. X                putword();
  796. X            }
  797. X}
  798. X
  799. X
  800. X^[ \t]+ {
  801. X            putword();
  802. X            if (iflag || obflag) {
  803. X                putline();
  804. X                tempi = attribute;
  805. X                /* for comments with indentation */
  806. X                if (cflag) attribute = ROMAN;
  807. X                copyindent(yytext);
  808. X                attribute = tempi;
  809. X            }
  810. X            else if (mflag)
  811. X                putline();
  812. X}
  813. X
  814. X<TEX,ALL>"\\ "        putword();
  815. X
  816. X<MAN,ALL,CCODE>\n  {    /* for C code reverse all of multiline comments */
  817. X            if (!cflag) attribute = ROMAN;
  818. X            nextattribute = qtflag = FALSE;
  819. X            /* signal end of tag for hanging indent */
  820. X            if (tpstate == 1) tpstate = 2;
  821. X            putword();
  822. X            if (obflag) putline();
  823. X}
  824. X
  825. X/* more font-changing */
  826. X
  827. X<MAN,ALL>^\.B" "    attribute = BOLD;
  828. X
  829. X<MAN,ALL>^\.(I|C)" "    attribute = ITALIC;
  830. X
  831. X<MAN,ALL>^\.R" "    attribute = ROMAN;
  832. X
  833. X<MAN,ALL>^\.("S"|"SM")" "    attribute = TTYPE;
  834. X
  835. X<MAN,ALL>^\.G" "    attribute = SLANTY;
  836. X
  837. X<MAN,ALL>\\[\|\^&!{}\nacdeprtuz]        ;
  838. X
  839. X<MAN,ALL>\\.        puttc(yytext[1]);
  840. X
  841. X<MAN,ALL>^".ti +"[0-9]+  {
  842. X             lbreak();
  843. X            for (tempi = 0; tempi < atoi(yytext+5) - 1; tempi++)
  844. X                puttc(' ');
  845. X}
  846. X
  847. X<MAN,ALL>^\.br         lbreak();
  848. X
  849. X<MAN,ALL>^\.(P|L|"")P     skipline(1); indent = 5;
  850. X
  851. X/* hanging indent stuff (awfully complicated) */
  852. X
  853. X<MAN,ALL>^\.(T|H)"P "[0-9]+\n  {
  854. X            skipline(1);
  855. X            if (yytext[1] == 'H')
  856. X                tpstate = 4;
  857. X            else    tpstate = 1;
  858. X            tpvalue = atoi(yytext+4);
  859. X            indent = 5;
  860. X}
  861. X
  862. X<TEX,ALL>\\"item"("item")?{wh}  |
  863. X<MAN,ALL>^".HP ".*\n    |
  864. X<MAN,ALL>^".TP".*\n    |
  865. X<MAN,ALL>^".IP"[ \t]*\n?  {
  866. X            skipline(1);
  867. X            if (yytext[1] == 'I' && yytext[3] == '\n')
  868. X                tpstate = 4;
  869. X            else    tpstate = 1;
  870. X            tpvalue = 5;
  871. X            indent = 5;
  872. X}
  873. X
  874. X/* various begin-end commands to set off blocks of text */
  875. X
  876. X<MAN,ALL>^"."(R|D)(S|E)  {
  877. X            if (yytext[1] == 'D' && yytext[2] == 'S') {
  878. X                skipline(1);
  879. X                obflag = TRUE;
  880. X            }
  881. X            else    lbreak();
  882. X            indent = 10;
  883. X            if (yytext[2] == 'E') {
  884. X                indent = 5;
  885. X                obflag = FALSE;
  886. X            }
  887. X}
  888. X
  889. X<MAN,ALL>^".E"(X|E)  {
  890. X            skipline(1);
  891. X            if (yytext[2] == 'E') {
  892. X                indent = 5;
  893. X                obflag = FALSE;
  894. X            }
  895. X            else {    indent = 10;
  896. X                obflag = TRUE;
  897. X            }
  898. X}
  899. X
  900. X
  901. X<MAN,ALL>^".N"(T|E).*  {
  902. X            skipline(1);
  903. X            if (yytext[2] == 'E') {
  904. X                indent = 5;
  905. X                maxlen += 5;
  906. X            }
  907. X            else {    indent = 10;
  908. X                maxlen -= 5;
  909. X                tempi = attribute;
  910. X                attribute = ITALIC;
  911. X                ceflag = TRUE;
  912. X                if (yyleng < 5) putts("NOTE");
  913. X                else putts(yytext+4);
  914. X                skipline(1);
  915. X            }
  916. X}
  917. X
  918. X/* those curious -man commands to join words, alternating fonts */
  919. X
  920. X<MAN,ALL>^\.("IR"|"PN")" "    nextattribute = ROMAN; attribute = ITALIC;
  921. X
  922. X<MAN,ALL>^\."BR "    nextattribute = ROMAN; attribute = BOLD;
  923. X
  924. X<MAN,ALL>^\."RI "    nextattribute = ITALIC; attribute = ROMAN;
  925. X
  926. X<MAN,ALL>^\."BI "    nextattribute = ITALIC; attribute = BOLD;
  927. X
  928. X<MAN,ALL>^\."RB "    nextattribute = BOLD; attribute = ROMAN;
  929. X
  930. X<MAN,ALL>^\."IB "    nextattribute = BOLD; attribute = ITALIC;
  931. X
  932. X/* section headings */
  933. X
  934. X<TEX,ALL>\\"beginsection"{wh}  {
  935. X            skipline(1);
  936. X            nextattribute = attribute;
  937. X            attribute = BOLD;
  938. X}
  939. X
  940. X<MAN,ALL>^\."S"(H|S)" ".* {
  941. X            skipline(1);
  942. X            if (yytext[2] == 'H')
  943. X                indent = 0;
  944. X            attribute = BOLD;
  945. X            putts(yytext+4);
  946. X            lbreak();
  947. X            indent = 5;
  948. X            attribute = ROMAN;
  949. X}
  950. X
  951. X<MAN,ALL>^\."TH ".* {
  952. X            lbreak();
  953. X            indent = 0;
  954. X            addparens(yytext+4, BOLD);
  955. X            raflag = TRUE;
  956. X            skipline(2);
  957. X            indent = 5;
  958. X}
  959. X
  960. X/* "Manual Section" reference */
  961. X<MAN,ALL>^".MS ".*    addparens(yytext+4, ITALIC);
  962. X
  963. X<MAN,ALL>^".CT ".  {
  964. X            if (uflag || oflag) {
  965. X                tempi = attribute;
  966. X                attribute = TTYPE;
  967. X                puttc(toupper(yytext[4]));
  968. X                attribute = tempi;
  969. X            }
  970. X            else {
  971. X                putts("<CTRL/");
  972. X                puttc(yytext[4]);
  973. X                puttc('>');
  974. X            }
  975. X}
  976. X
  977. X<MAN,ALL>^".V"(S|E).* |
  978. X<MAN,ALL>^".UC"(..)?  |
  979. X<MAN,ALL>^\.\\\".*    ;
  980. X
  981. X/* for join-words commands, words can be quoted */
  982. X<MAN,ALL>\"  {
  983. X            if (nextattribute || tpstate == 1)  {
  984. X                qtflag = !qtflag;
  985. X            }
  986. X            else puttc('"');
  987. X}
  988. X
  989. X<MAN,ALL,CCODE>" "  {
  990. X            if (nextattribute)  {
  991. X                if (qtflag) puttc(' ');
  992. X                else  {
  993. X                    tempi = attribute;
  994. X                    attribute = nextattribute;
  995. X                    nextattribute = tempi;
  996. X                }
  997. X            }
  998. X            else {
  999. X                putword();
  1000. X                if (obflag) copyindent(yytext);
  1001. X            }
  1002. X}
  1003. X
  1004. X<TEX,ALL,CCODE>\n  {
  1005. X            putword();
  1006. X            if (obflag || nextattribute) putline();
  1007. X            if (nextattribute) {
  1008. X                attribute = nextattribute;
  1009. X                nextattribute = 0;
  1010. X            }
  1011. X}
  1012. X
  1013. X<TEX,ALL>"~"            puttc(' ');
  1014. X
  1015. X[ \t]+  {
  1016. X            putword();
  1017. X            if (obflag) copyindent(yytext);
  1018. X}
  1019. X
  1020. X[\n\r\f]            putword();
  1021. X
  1022. X<TEX,ALL>\\"backslash"{wh}    puttc('\\');
  1023. X
  1024. X<TEX>\\    |
  1025. X<TEX,ALL>\$|\#            ;
  1026. X
  1027. X<TEX,ALL>\\[A-Za-z]+{wh}    ;
  1028. X
  1029. X<MAN,ALL>\\"*(rq"    puttc('\'');
  1030. X
  1031. X<MAN,ALL>\\"*(lq"    puttc('`');
  1032. X
  1033. X<MAN,ALL>\\"("..  {
  1034. X            tempi = attribute;
  1035. X            attribute = TTYPE;
  1036. X            if (yytext[2] != '*') puttc(yytext[2]);
  1037. X            puttc(yytext[3]);
  1038. X            attribute = tempi;
  1039. X}
  1040. X
  1041. X<MAN,ALL>\\"s"("-")?[0-9] |
  1042. X<MAN,ALL>"\\*S"        |
  1043. X<MAN,ALL>^".DT"        |
  1044. X<MAN,ALL>^".ta ".*    |
  1045. X<MAN,ALL>^".PD".*    |
  1046. X<MAN,ALL>^".NX".*    ;
  1047. X
  1048. X<CCODE>\"    {    if (attribute != TTYPE) qtflag = !qtflag;
  1049. X            puttc('"');
  1050. X}
  1051. X
  1052. X<CCODE>"/*"    {    puttc('/');
  1053. X            if (!qtflag) attribute = TTYPE;
  1054. X            puttc('*');
  1055. X}
  1056. X
  1057. X<CCODE>"*/"    {    puttc('*');
  1058. X            if (!qtflag) attribute = ROMAN;
  1059. X            puttc('/');
  1060. X}
  1061. X
  1062. X/* control flow keywords are bold */
  1063. X<CCODE>"continue"|"default"|"do"|"goto"|"return"  |
  1064. X<CCODE>"if"|"else"|"while"|"break"|"switch"|"case"|"for"  {
  1065. X            if (attribute != TTYPE && !qtflag) {
  1066. X                attribute = BOLD;
  1067. X                putts(yytext);
  1068. X                attribute = ROMAN;
  1069. X            } else putts(yytext);
  1070. X}
  1071. X
  1072. X/* storage class keywords are underlined */
  1073. X<CCODE>("auto"|"char"|"double"|"enum"|"extern"|"float")  |
  1074. X<CCODE>("int"|"long"|"register"|"short"|"sizeof"|"static") |
  1075. X<CCODE>("struct"|"typedef"|"union"|"unsigned"|"void") {
  1076. X
  1077. X            if (attribute != TTYPE && !qtflag) {
  1078. X                attribute = ITALIC;
  1079. X                putts(yytext);
  1080. X                attribute = ROMAN;
  1081. X            } else putts(yytext);
  1082. X}
  1083. X
  1084. X/* preprocessor keywords are blinking */
  1085. X<CCODE>"#"[ \t]*("define"|"undef"|"include"|"if"|"ifdef")  |
  1086. X<CCODE>"#"[ \t]*("ifndef"|"else"|"endif"|"line")  {
  1087. X
  1088. X            if (attribute != TTYPE && !qtflag) {
  1089. X                attribute = SLANTY;
  1090. X                putts(yytext);
  1091. X                attribute = ROMAN;
  1092. X            } else putts(yytext);
  1093. X}
  1094. X
  1095. X/* identifiers that happen to contain keywords are plain */
  1096. X<CCODE>[a-zA-Z_]+    putts(yytext);
  1097. X
  1098. X.            puttc(yytext[0]);
  1099. X
  1100. X
  1101. X
  1102. X%%
  1103. X
  1104. X/*
  1105. X * Characters, along with the currently active "font"= screen
  1106. X * attribute, are collected in a word buffer until we hit a
  1107. X * word break (white space), then moved to a line buffer.
  1108. X * Words are collected in the line buffer until we hit a line
  1109. X * break (end of paragraph) or the line is long enough, then
  1110. X * the line is output.
  1111. X */
  1112. X
  1113. main (argc, argv)
  1114. int     argc;
  1115. char   *argv[];
  1116. X{
  1117. X    int     c, i;
  1118. X
  1119. X    progname = basename (argv[0]);
  1120. X    while ((c = getopt (argc, argv, "ijcxmoul:p:t:")) != EOF)
  1121. X        switch (c) {
  1122. X            case 'i': iflag = TRUE; break;
  1123. X            case 'j': jflag = TRUE; break;
  1124. X            case 'c': cflag = TRUE; break;
  1125. X            case 'x': xflag = TRUE; break;
  1126. X            case 'm': mflag = TRUE; break;
  1127. X            case 'o': oflag = TRUE; break;
  1128. X            case 'u': uflag = TRUE; break;
  1129. X            case 'l': maxlen = max (0, atoi (optarg));
  1130. X                  break;
  1131. X            case 'p': offset = max (0, atoi (optarg));
  1132. X                  break;
  1133. X            case 't': tabsize = max (1, atoi (optarg));
  1134. X                  break;
  1135. X            default: (void) fprintf (stderr, usage, progname);
  1136. X                  exit (1);
  1137. X                  break;
  1138. X        }
  1139. X
  1140. X
  1141. X/* set lex start state */
  1142. X    if (xflag && mflag) {
  1143. X        BEGIN (ALL);
  1144. X    }
  1145. X    else if (xflag) {
  1146. X        BEGIN (TEX);
  1147. X    }
  1148. X    else if (mflag) {
  1149. X        indent = 5;
  1150. X        BEGIN (MAN);
  1151. X    }
  1152. X    else if (cflag) {
  1153. X        obflag = TRUE;
  1154. X        if (!oflag) uflag = TRUE;
  1155. X        BEGIN (CCODE);
  1156. X    }
  1157. X    else {
  1158. X        BEGIN (PLAIN);
  1159. X    }
  1160. X
  1161. X/* consult termcap for terminal controls */
  1162. X    if (uflag)
  1163. X        terminit ();
  1164. X
  1165. X
  1166. X/* call lex scanner */
  1167. X    if (optind >= argc) {
  1168. X        (void) yylex ();
  1169. X        lbreak ();
  1170. X    }
  1171. X    else
  1172. X        for (; (optind < argc); optind++) {
  1173. X            if (freopen (argv[optind], "r", yyin) != NULL) {
  1174. X                /* unstructured -- couldn't find any other
  1175. X                 * way to get flex to look at > 1 file */
  1176. X                yy_init = 1;
  1177. X                (void) yylex ();
  1178. X                lbreak ();
  1179. X            }
  1180. X            else {
  1181. X                (void) fprintf (stderr,
  1182. X                    "Couldn't open file: %s", argv[optind]);
  1183. X                exit (1);
  1184. X            }
  1185. X        }
  1186. X
  1187. X    return (0);
  1188. X}                /* main */
  1189. X
  1190. X
  1191. X/* preserve spacing due to spaces or tabs */
  1192. void    copyindent (ilp)
  1193. char    *ilp;
  1194. X{
  1195. X    int     col;
  1196. X
  1197. X    col = (olp - oline) + 1;
  1198. X
  1199. X    for (; (isspace (*ilp)); col++) {
  1200. X        if (*ilp++ == '\t')
  1201. X            for (; (col % tabsize); col++) {
  1202. X                *olp++ = ' ';
  1203. X                *alp++ = (cflag) ? attribute : ROMAN;
  1204. X            }
  1205. X        *olp++ = ' ';
  1206. X        *alp++ = (cflag) ? attribute : ROMAN;
  1207. X    }
  1208. X}                /* copyindent */
  1209. X
  1210. X/* one character goes into word buffer */
  1211. void puttc (ch)
  1212. char    ch;
  1213. X{
  1214. X    *owp++ = ch;
  1215. X    *awp++ = attribute;
  1216. X}                /* puttc */
  1217. X
  1218. X/* put string in word buffer (might have spaces) */
  1219. void putts (s)
  1220. char   *s;
  1221. X{
  1222. X    while (*s)
  1223. X        puttc (*s++);
  1224. X}                /* putts */
  1225. X
  1226. X/* finish pending word and line and put it out (no justification) */
  1227. void lbreak () {
  1228. X    putword ();
  1229. X    putline ();
  1230. X    tpstate = 0;
  1231. X}                /* lbreak */
  1232. X
  1233. X/* append pending word to line buffer */
  1234. void putword () {
  1235. X    int     plen;
  1236. X    char   *p;
  1237. X    char   *q;
  1238. X    static char     started = 0;
  1239. X
  1240. X    /* just return if no characters have been accumulated yet */
  1241. X    if (owp == oword) {
  1242. X        /* this is for the special case in which a file
  1243. X         * starts with \n, which should count as  a "blank line"
  1244. X         */
  1245. X        if (!started) {
  1246. X            putchar ('\n');
  1247. X            started = 1;
  1248. X        }
  1249. X        return;
  1250. X    }
  1251. X    started = 1;
  1252. X
  1253. X    puttc ('\0');
  1254. X    p = oword;
  1255. X    q = aword;
  1256. X    plen = strlen (p);
  1257. X
  1258. X    /* ugly way to ignore "0.3i" arg of .IP */
  1259. X    if (tpstate == 2 && *p == '0' && p[plen - 1] == 'i') {
  1260. X        spaces = plen = 0;
  1261. X        *p = '\0';
  1262. X    }
  1263. X
  1264. X    /* finish pending line if pending word won't fit */
  1265. X    if (!obflag && (olp - oline) + spaces + plen > maxlen - indent) {
  1266. X        if ((jflag) && (holecnt) && !njflag)
  1267. X            justifyline ();
  1268. X        putline ();
  1269. X    }
  1270. X
  1271. X    /* append spaces which were previously decided to go after
  1272. X     * last word put in line buffer */
  1273. X    if (spaces) {
  1274. X        /* don't use space inside tag of hanging indent to
  1275. X         * right justify */
  1276. X        if (!tpstate || tpstate > 3)
  1277. X            holeptr[++holecnt] = olp;
  1278. X        /* if tag already padded out, permit justification
  1279. X         * of space after next word */
  1280. X        if (tpstate == 3)
  1281. X            tpstate = 4;
  1282. X        for (; (spaces > 0); spaces--) {
  1283. X            *olp++ = ' ';
  1284. X            /* a matter of taste -- put just " = ROMAN"
  1285. X             * for no underlined spaces between words */
  1286. X            *alp++ = (*(alp-1) == ITALIC && *q == ITALIC) ?
  1287. X                ITALIC : ROMAN;
  1288. X        }
  1289. X    }
  1290. X
  1291. X    /* figure spaces which should go after pending word which
  1292. X     * is just about to be appended in line buffer -- remember
  1293. X     * so they can be put before next word (cf. just above) */
  1294. X    if (!obflag) spaces = 1 + endofsentence (p, plen);
  1295. X    /* (but if spacing is being preserved, as signaled by
  1296. X     *  obflag, we don't want extra spaces) */
  1297. X
  1298. X    /* append pending word in line buffer */
  1299. X    while (*p) {
  1300. X        *olp++ = *p++;
  1301. X        *alp++ = *q++;
  1302. X    }
  1303. X
  1304. X    /* part of tortuous way of handling hanging indent */
  1305. X        /* tpstate = 0: no hanging indent
  1306. X         *         1: scanning tag to go in left margin
  1307. X         *         2: have seen end of tag, time to
  1308. X         *        pad out tag to hanging indent value
  1309. X         *         3: finished padding
  1310. X         *         4: finished first line of hanging par.;
  1311. X         *        subsequent lines should be indented
  1312. X         *        to hanging indent value
  1313. X         */
  1314. X    if (tpstate == 2) {    /* time to pad tag? */
  1315. X        tpstate = 3;    /* signal padding done */
  1316. X        if ((olp - oline) + spaces > tpvalue) /* will tag fit? */
  1317. X            putline ();    /* no it won't, so start new line */
  1318. X        else        /* yes it will, so pad it out */
  1319. X            while ((olp - oline) + spaces < tpvalue)
  1320. X                spaces++;
  1321. X    }
  1322. X
  1323. X    /* purge word buffer -- get ready for next word */
  1324. X    owp = oword;
  1325. X    awp = aword;
  1326. X}                /* putword */
  1327. X
  1328. X
  1329. X/* increase inter-word spacings for right justification */
  1330. void justifyline () {
  1331. X    int     n;
  1332. X    char   *fp,
  1333. X           *tp,
  1334. X           *fa,
  1335. X           *ta;
  1336. X
  1337. X    dir = (!(dir));
  1338. X    fp = olp - 1;
  1339. X    fa = alp - 1;
  1340. X    olp = &oline[maxlen - indent];
  1341. X    alp = &aline[maxlen - indent];
  1342. X    tp = olp - 1;
  1343. X    ta = alp - 1;
  1344. X    while (tp > fp) {
  1345. X        while (fp >= holeptr[holecnt]) {
  1346. X            *tp-- = *fp--;
  1347. X            *ta-- = *fa--;
  1348. X        }
  1349. X        if (dir)
  1350. X            n = ((tp - fp) - 1) / holecnt + 1;
  1351. X        else
  1352. X            n = (tp - fp) / holecnt;
  1353. X        while (n--) {
  1354. X            *tp-- = ' ';
  1355. X            *ta-- = ta[1];
  1356. X        }
  1357. X        holecnt--;
  1358. X    }
  1359. X}                /* justifyline */
  1360. X
  1361. X
  1362. X/* put out pending line in line buffer */
  1363. void putline ()
  1364. X{
  1365. X    if (ceflag) {
  1366. X        spaces = max ((maxlen - (olp - oline)) / 2, 1) + offset;
  1367. X        ceflag = FALSE;
  1368. X    }
  1369. X    else if (raflag) {
  1370. X        spaces = max ((maxlen - (olp - oline)), 1) + offset;
  1371. X        raflag = FALSE;
  1372. X    }
  1373. X    else    spaces = indent + offset;
  1374. X
  1375. X    *olp = '\0';
  1376. X
  1377. X    if (*oline)
  1378. X        /* if -u or -x options, have to do it character
  1379. X         * by character */
  1380. X        if (oflag || uflag)
  1381. X            sputline ();
  1382. X    else
  1383. X            (void) printf ("%*s\n", spaces + strlen (oline), oline);
  1384. X
  1385. X    /* purge line buffer -- get ready for new line */
  1386. X    *oline = '\0';
  1387. X    olp = oline;
  1388. X    alp = aline;
  1389. X    spaces = 0;
  1390. X    holecnt = 0;
  1391. X
  1392. X    /* if finished with first line of hanging par., increase
  1393. X     * left indent for subsequent lines */
  1394. X    if (tpstate > 2) {
  1395. X        indent = tpvalue + 5;
  1396. X        tpstate = 4;
  1397. X    }
  1398. X}                /* putline */
  1399. X
  1400. X
  1401. X/* display characters of line with overstriking or with special
  1402. X * terminal attributes */
  1403. void sputline () {
  1404. X    char   *p;
  1405. X    char   *q;
  1406. X    char    last = ROMAN;
  1407. X
  1408. X    if (spaces)
  1409. X        (void) printf ("%*s", spaces, NULL);
  1410. X
  1411. X    for (p = oline, q = aline; *p; p++, q++)
  1412. X        if (uflag) {
  1413. X            last = newattr (last, *q);
  1414. X            (void) printf ("%c", *p);
  1415. X        } else
  1416. X        switch (*q) {
  1417. X            case ROMAN: 
  1418. X                (void) printf ("%c", *p);
  1419. X                break;
  1420. X            case BOLD: 
  1421. X            case TTYPE: 
  1422. X                if (*p == ' ')
  1423. X                    printf("%c", *p);
  1424. X                else    (void) printf ("%c%c%c", *p, 8, *p);
  1425. X                break;
  1426. X            case ITALIC: 
  1427. X            case SLANTY: 
  1428. X                (void) printf ("_%c%c", 8, *p);
  1429. X                break;
  1430. X        }
  1431. X    if (uflag)
  1432. X        last = newattr (last, ROMAN);
  1433. X    (void) printf ("\n");
  1434. X
  1435. X}                /* sputline */
  1436. X
  1437. X/* put blank lines */
  1438. void skipline (n)
  1439. int     n;
  1440. X{
  1441. X    lbreak ();
  1442. X    for (; (n > 0); n--)
  1443. X        (void) printf ("\n");
  1444. X    if (xflag)
  1445. X        indent = 0;
  1446. X}                /* skipline */
  1447. X
  1448. X
  1449. X/* decide how many spaces go after word */
  1450. int     endofsentence (p, plen)
  1451. char   *p;
  1452. int     plen;
  1453. X{
  1454. X    if (plen < 3)
  1455. X        return (FALSE);
  1456. X    if (!strchr (".:?!", *(p + plen - 1)))
  1457. X        return (FALSE);
  1458. X    if (abbr (p))
  1459. X        return (FALSE);
  1460. X    return (TRUE);
  1461. X}                /* endofsentence */
  1462. X
  1463. X
  1464. X/* detect "." which is not real end of sentence */
  1465. int     abbr (s)
  1466. char   *s;
  1467. X{
  1468. X    char   *p,
  1469. X           *q,
  1470. X           *r;
  1471. X
  1472. X    while (*s == '(')
  1473. X        s++;
  1474. X    q = ".i.e.g.dr.mr.mrs.st.";
  1475. X    for (; (*q); q++) {
  1476. X        p = q;
  1477. X        r = s;
  1478. X        while ((*r) && (*p++ == (*r++ | 0x20)));
  1479. X        if (!*r)
  1480. X            return (TRUE);
  1481. X    }
  1482. X    return (FALSE);
  1483. X}                /* abbr */
  1484. X
  1485. X
  1486. X
  1487. char   *basename (s)
  1488. char   *s;
  1489. X{
  1490. X    char   *p;
  1491. X
  1492. X    if (p = strrchr (s, '/'))
  1493. X        return (++p);
  1494. X    else
  1495. X        return (s);
  1496. X}                /* basename */
  1497. X
  1498. X
  1499. X
  1500. int     max (a, b)
  1501. int     a,
  1502. X        b;
  1503. X{
  1504. X    return ((a > b) ? a : b);
  1505. X}                /* max */
  1506. X
  1507. X
  1508. X/* put parentheses around number of manual section */
  1509. void addparens (s, a)
  1510. char   *s;
  1511. int     a;
  1512. X{
  1513. X    nextattribute = attribute;
  1514. X    attribute = a;
  1515. X    while (*s && *s != ' ')
  1516. X        puttc (*s++);
  1517. X    if (*s == ' ')
  1518. X        s++, puttc ('(');
  1519. X    while (*s && *s != ' ')
  1520. X        puttc (*s++);
  1521. X    if (*s == ' ')
  1522. X        s++;
  1523. X    puttc (')');
  1524. X    attribute = nextattribute;
  1525. X    nextattribute = 0;
  1526. X    if (*s && isalpha (*s))
  1527. X        puttc (' ');
  1528. X    while (*s)
  1529. X        puttc (*s++);
  1530. X}                /* addparens */
  1531. X
  1532. X/* terminal commands -- accessing routines */
  1533. X
  1534. X/*
  1535. X *  following derived from:
  1536. X *  tcap v1.0 Enhanced terminal control program
  1537. X *  Author: Eric Lorenzo Lim
  1538. X *  Modified by: Becca Thomas and Rik Farrow
  1539. X *  (appeared in Nov. '87 Unix World)
  1540. X */
  1541. X
  1542. X#define SO 0
  1543. X#define SE 1
  1544. X#define MB 2
  1545. X#define MD 3
  1546. X#define MR 4
  1547. X#define MH 5
  1548. X#define ME 6
  1549. X#define US 7
  1550. X#define UE 8
  1551. char   *id[] = {
  1552. X    "so", "se", "mb", "md", "mr", "mh", "me", "us", "ue",
  1553. X    (char *) NULL,
  1554. X};
  1555. X
  1556. char   *area[50];
  1557. char    bp[1024],
  1558. X        strbuf[1024];
  1559. X
  1560. X/* get for later use terminal handling commands we need */
  1561. void terminit () {
  1562. X    int     id_size = 0;
  1563. X    char   *str,
  1564. X           *tmpptr;
  1565. X    extern char    *getenv (), *tgetstr (), *tgoto ();
  1566. X
  1567. X    if ((tmpptr = getenv ("TERM")) == (char *) NULL) {
  1568. X        (void) fprintf (stderr, "xfmt: TERM variable not set\n");
  1569. X        exit (1);
  1570. X    }
  1571. X
  1572. X    str = strbuf;
  1573. X
  1574. X    if (tgetent (bp, tmpptr))
  1575. X        while (id[id_size] != (char *) NULL) {
  1576. X            area[id_size] = tgetstr (id[id_size], &str);
  1577. X            if (area[id_size] == (char *) NULL)
  1578. X                area[id_size] = "";
  1579. X            id_size++;
  1580. X        }
  1581. X
  1582. X
  1583. X}                /* terminit */
  1584. X
  1585. X/* put out a terminal handing command */
  1586. void termattr (i)
  1587. int     i;
  1588. X{
  1589. X    (void) printf ("%s", area[i]);
  1590. X}                /* termattr */
  1591. X
  1592. X/* check for change of "font" and send command to terminal
  1593. X * when there is a change */
  1594. int     newattr (l, a)
  1595. int     l,    /* last attribute */
  1596. X        a;    /* new attribute */
  1597. X{
  1598. X    if (l != a) {
  1599. X        if (l == BOLD || l == TTYPE || l == SLANTY)
  1600. X            termattr (ME);
  1601. X        else if (l == ITALIC)
  1602. X            termattr (UE);
  1603. X
  1604. X        switch (a) {
  1605. X            case   BOLD:    termattr (MD); break;
  1606. X            case ITALIC:    termattr (US); break;
  1607. X            case  TTYPE:    termattr (MR); break;
  1608. X            case SLANTY:    termattr (MB); break;
  1609. X        }
  1610. X    }
  1611. X    return (a);
  1612. X}                /* newattr */
  1613. X
  1614. END_OF_FILE
  1615. if test 21023 -ne `wc -c <'xfmt.l'`; then
  1616.     echo shar: \"'xfmt.l'\" unpacked with wrong size!
  1617. fi
  1618. # end of 'xfmt.l'
  1619. fi
  1620. echo shar: End of archive 1 \(of 1\).
  1621. cp /dev/null ark1isdone
  1622. MISSING=""
  1623. for I in 1 ; do
  1624.     if test ! -f ark${I}isdone ; then
  1625.     MISSING="${MISSING} ${I}"
  1626.     fi
  1627. done
  1628. if test "${MISSING}" = "" ; then
  1629.     echo You have the archive.
  1630.     rm -f ark[1-9]isdone
  1631. else
  1632.     echo You still need to unpack the following archives:
  1633.     echo "        " ${MISSING}
  1634. fi
  1635. ##  End of shell archive.
  1636. exit 0
  1637.  
  1638.          -- Greg, lee@uhccux.uhcc.hawaii.edu
  1639.  
  1640.